package com.zp.qualitypractice.rx;

import android.support.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import io.reactivex.Observable;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;

/**
 * Created by izp on 2017/8/11.
 */

public class RxBus {
    //所有事件的CODE
    public static final int EXEPTION = 1; //点击事件
    public static final int PRESSURE = 21; //其它事件
    public static final int ORDINARY = 20; //其它事件

    //枚举
    @IntDef({EXEPTION, PRESSURE,ORDINARY})
    public @interface BusType {}


    private static volatile RxBus defaultInstance;

    private final Subject<Object> bus;



    // PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者
    private RxBus() {
        bus = PublishSubject.create().toSerialized();
    }
//    private RxBus(@BusType int type){
//
//    }

    // 单例RxBus
    public static RxBus getDefault() {
        if (defaultInstance == null) {
            synchronized (RxBus.class) {
                if (defaultInstance == null) {
                    defaultInstance = new RxBus();
                }
            }
        }
        return defaultInstance;
    }

    // 发送一个新的事件，所有订阅此事件的订阅者都会收到
    public void post(Object action) {
        bus.onNext(action);
    }

    // 用 code 指定订阅此事件的对应 code 的订阅者
    public void postWithCode(int code, Object action) {
        bus.onNext(new RxAction(code, action));
    }


    // 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者
    public <T> Observable<T> toObservable(Class<T> eventType) {
        return bus.ofType(eventType);
    }

    // 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者,
    public <T> Observable<T> toObservableWithCode(final int code, Class<T> eventType) {
        return bus.ofType(RxAction.class)
                .filter(new Predicate<RxAction>() {
                    @Override
                    public boolean test(RxAction eyeAction) throws Exception {
                        return eyeAction.code == code;
                    }
                })
                .map(new Function<RxAction, Object>() {
                    @Override
                    public Object apply(RxAction eyeAction) throws Exception {
                        return eyeAction.data;
                    }
                })
                .cast(eventType);
    }
}
